define([
	'goo/entities/components/Component',
	'goo/math/Vector3',
	'goo/util/GameUtils',
	'js/io/Input',
	'js/application/Game',
	'js/application/Time',
	'goo/renderer/Camera',
	'goo/entities/components/CameraComponent',
	'goo/entities/EntityUtils',
	'js/movement/SphereMovement'
], function(
	Component,
	Vector3,
	GameUtils,
	Input,
	Game,
	Time,
	Camera,
	CameraComponent,
	EntityUtils,
	SphereMovement
) {
	'use strict';
	function FPSCamComponent(sphereEntity){
		this.type = "FPSCamComponent";

		this.speed = 10;

		this.fwdBase = new Vector3(-1,0,0);
		this.leftBase = new Vector3(0,0,1);
		this.direction = new Vector3(0,0,1);
		this.left = new Vector3(1,0,0);
		this.movement = new Vector3(1,0,0);

		this.oldPos = new Vector3();
		this.newPos = new Vector3();
		this.oldYaw = 0;
		this.newYaw = 0;
		this.oldPitch = 0;
		this.newPitch = 0;

		//var wantPos = new Vector3(0,0,0);
		//var wantMove = new Vector3();

		this.torqueVector = new Ammo.btVector3(0, 0, 0);
        this.sphereEntity = sphereEntity;
        this.sphereTransform = sphereEntity.transformComponent.transform;
        this.ammoComponent = this.sphereEntity.ammoComponent;
        this.sphereMovement = new SphereMovement();

		this.moveEntity = Game.goo.world.createEntity("UserRoot");
		Game.userEntity = this.moveEntity;
		this.moveEntity.addToWorld();
		this.moveTransform = this.moveEntity.transformComponent.transform;

		this.cam = EntityUtils.createTypicalEntity(Game.goo.world, new Camera(45, 1.0, 0.1, 1300));
		Game.viewCam = this.cam;
		this.camTransform = this.cam.transformComponent.transform;
		this.cam.addToWorld();
		
		this.moveEntity.transformComponent.attachChild(this.cam.transformComponent);
		this.moveEntity.transformComponent.setUpdated();
		Game.register("MouseMove", this, mouseMove);
		Game.register("MouseButton1", this, mouseDown1);
		//Game.register("FixedUpdate", this, fixedUpdate);
		Game.register("Update", this, update);
		//Game.register("RenderUpdate", this, renderUpdate);
	}

	FPSCamComponent.prototype = Object.create(Component.prototype);
	FPSCamComponent.prototype.setHeight = function(n0){
		this.cam.transformComponent.transform.translation.y = n0;
		this.cam.transformComponent.setUpdated();
	};



    FPSCamComponent.prototype.sampleInputState = function() {

        if (true == Input.keys[87]) // W
            this.movement.add(this.direction);
        if (true == Input.keys[83]) // S
            this.movement.sub(this.direction);
        if (true == Input.keys[65]) // A
            this.movement.add(this.left);
        if (true == Input.keys[68]) // D
            this.movement.sub(this.left);
        if (true == Input.keys[32]) { // space bar
            this.sphereMovement.applyJump(1);
        }
    };

	function mouseMove() {
	//	if(!document.pointerLockElement){return;}
		
		this.oldPitch = this.newPitch; 
		this.newPitch = this.oldPitch - Input.movement.y * 0.015;

		if(this.newPitch > Math.PI*0.5){
			this.newPitch = Math.PI*0.5;
		}
		if(this.newPitch < -Math.PI*0.5){
			this.newPitch = -Math.PI*0.5;
		}

		this.camTransform.rotation.fromAngles(this.newPitch, 0, 0);
		this.cam.transformComponent.setUpdated();


		this.oldYaw = this.sphereMovement.controlState.yaw;
		this.newYaw = this.oldYaw - Input.movement.x * 0.015;
		this.ammoComponent.activate();
		this.sphereMovement.applyTurn(this.newYaw);
		this.moveTransform.rotation.fromAngles(0,this.sphereMovement.controlState.yaw,0);
		this.moveEntity.transformComponent.setUpdated();
	}

	function mouseDown1(t) {
		if(true == t){
			if(!document.pointerLockElement) {
			//	GameUtils.requestPointerLock();
			}
		}
	}

	var calcVec = new Vector3();
	function update(){
           // console.log("Walk the sphere: ", this.sphereEntity)
            this.grounded = false;
			this.oldPos.copy(this.newPos);

            //zombieTransform.transform.translation.set(physTransform.transform.translation);
            //zombieTransform.setUpdated();

			this.moveTransform.applyForwardVector( this.fwdBase, this.direction); // get the direction the camera is looking
			this.moveTransform.applyForwardVector( this.leftBase, this.left); // get the direction to the left of the camera

			this.movement.copy(Vector3.ZERO);

            this.sampleInputState();


			this.movement.y = 0;
			this.movement.normalize(); // move the same amount regardless of where we look-

          	//this.applyMovementState(this.selectMovementState());
          	this.sphereMovement.applyForward(this.movement.z * this.speed /** Math.sin(this.sphereMovement.controlState.yaw * (Math.PI/180))*/);
			this.sphereMovement.applyStrafe(this.movement.x * this.speed /** Math.cos(this.sphereMovement.controlState.yaw * (Math.PI/180))*/);

            this.sphereMovement.updateTargetVectors();
            var targetVelocity = this.sphereMovement.getTargetVelocity();

            // This torqueVector currently applies arbitrary directional rotation to the sphere. This needs
            // to know the orientation of the gamepiece to roll it in the correct direction.
            this.torqueVector.setValue(0,0,0);
            this.ammoComponent.setAngularVelocity(this.torqueVector);

            this.torqueVector.setValue(targetVelocity.data[0], targetVelocity.data[1],targetVelocity.data[2]);

            this.ammoComponent.clearForces();

            this.ammoComponent.applyTorqueImpulse(this.torqueVector);

            if(targetVelocity.data[1] != 0) {
                this.torqueVector.setValue(0, targetVelocity.data[1], 0);
                this.ammoComponent.applyCentralImpulse(this.torqueVector);
             //   this.sphereMovement.groundContact = 0;
            }
            this.ammoComponent.activate();

            this.moveTransform.translation.set(this.sphereTransform.translation);
            this.moveEntity.transformComponent.setUpdated();
	}

	return FPSCamComponent;
});